package com.shop.cereshop.app.controller.order;

import com.shop.cereshop.app.annotation.NoRepeatSubmit;
import com.shop.cereshop.app.annotation.NoRepeatWebLog;
import com.shop.cereshop.app.dao.after.CereOrderAfterDAO;
import com.shop.cereshop.app.dao.dl.CereShopProductMapper;
import com.shop.cereshop.app.dl.logic.domain.CereShopProduct;
import com.shop.cereshop.app.page.cart.CartSku;
import com.shop.cereshop.app.page.order.*;
import com.shop.cereshop.app.page.settlement.Settlement;
import com.shop.cereshop.app.param.comment.CommentSaveParam;
import com.shop.cereshop.app.param.order.OrderGetAllParam;
import com.shop.cereshop.app.param.order.OrderGetByIdParam;
import com.shop.cereshop.app.param.order.OrderParam;
import com.shop.cereshop.app.param.order.PayParam;
import com.shop.cereshop.app.param.settlement.ProductSku;
import com.shop.cereshop.app.param.settlement.SettlementParam;
import com.shop.cereshop.app.param.settlement.ShopProductParam;
import com.shop.cereshop.app.service.dict.CerePlatformDictService;
import com.shop.cereshop.app.service.order.CereShopOrderService;
import com.shop.cereshop.app.service.product.CereShopProductService;
import com.shop.cereshop.app.weixin.skd.HttpKit;
import com.shop.cereshop.app.weixin.skd.PaymentKit;
import com.shop.cereshop.commons.constant.CoReturnFormat;
import com.shop.cereshop.commons.constant.StringEnum;
import com.shop.cereshop.commons.domain.after.CereAfterDilever;
import com.shop.cereshop.commons.domain.buyer.CereBuyerUser;
import com.shop.cereshop.commons.domain.common.Page;
import com.shop.cereshop.commons.domain.dict.CerePlatformDict;
import com.shop.cereshop.commons.domain.order.CereOrderProduct;
import com.shop.cereshop.commons.exception.CoBusinessException;
import com.shop.cereshop.commons.result.Result;
import com.shop.cereshop.commons.utils.AppletPayUtil;
import com.shop.cereshop.commons.utils.EmptyUtils;
import com.shop.cereshop.commons.utils.GsonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 订单模块
 */
@RestController
@RequestMapping("order")
/**
 * 注解方式生成日志对象，指定topic生成对象类名
 */
@Slf4j(topic = "OrderController")
@CrossOrigin
@Api(value = "订单模块", tags = "订单模块")
public class OrderController {

    @Autowired
    private CereShopOrderService cereShopOrderService;
    @Autowired
    private CereShopProductMapper cereShopProductMapper;
    @Autowired
    private CereShopProductService cereShopProductService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CerePlatformDictService cerePlatformDictService;

    @Autowired
    private CereOrderAfterDAO cereOrderAfterDAO;

    /**
     * 商户秘钥
     */
    @Value("${weixin.key}")
    private String key;

    /**
     * 结算查询
     *
     * @param param
     * @return
     */
    @PostMapping("getSettlement")
    @ApiOperation(value = "结算查询")
    public Result<Settlement> getSettlement(@RequestBody SettlementParam param, HttpServletRequest request) throws CoBusinessException {
        List<ShopProductParam> shops = param.getShops();
        for (ShopProductParam sp:shops){
            List<ProductSku> skus = sp.getSkus();
            for (ProductSku sk:skus){
                Integer a = cereShopProductMapper.selByShopIdAndSkuId(sp.getShopId(),sk.getSkuId());
              if (a==null || a!=1){
                  throw new CoBusinessException(CoReturnFormat.REFRESH);
              }
            }
        }
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        Settlement settlement = cereShopOrderService.getSettlement(param, user);
        Long productId = settlement.getShops().get(0).getSkus().get(0).getProductId();
        CereShopProduct shopProduct = cereShopProductMapper.selectByPrimaryKey(productId);
        settlement.getShops().get(0).getSkus().get(0).setPurchaseNotes(shopProduct.getPurchaseNotes());
        return new Result(settlement, CoReturnFormat.SUCCESS);
    }

    /**
     * 提交订单
     *
     * @param param
     * @return
     */
    @PostMapping("submit")
    @NoRepeatSubmit
    @ApiOperation(value = "提交订单")
    @NoRepeatWebLog
    public Result submit(@RequestBody OrderParam param, HttpServletRequest request) throws CoBusinessException, Exception {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        String ip = AppletPayUtil.getClientIp(request);
        PayUrl payUrl = cereShopOrderService.submit(param, user, ip);
        return new Result(payUrl, CoReturnFormat.SUCCESS, user.getWechatName(), "提交订单", GsonUtil.objectToGson(param));
    }

    /**
     * 根据订单id获取收款码
     *
     * @param param
     * @return
     */
    @GetMapping("getUrl")
    @NoRepeatSubmit
    @ApiOperation(value = "根据订单id获取收款码")
    public Result getUrl(OrderGetByIdParam param, HttpServletRequest request) throws CoBusinessException, Exception {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        String ip = AppletPayUtil.getClientIp(request);
        PayUrl payUrl = cereShopOrderService.getUrl(param, user, ip);
        return new Result(payUrl, CoReturnFormat.SUCCESS);
    }

    /**
     * 校验当前订单是否支付成功
     *
     * @param param
     * @return
     */
    @GetMapping("checkPay")
    @NoRepeatSubmit
    @ApiOperation(value = "校验当前订单是否支付成功")
    public Result checkPay(PayParam param) throws CoBusinessException {
        PayUrl payUrl = cereShopOrderService.checkPay(param);
        return new Result(payUrl, CoReturnFormat.SUCCESS);
    }

    /**
     * 订单管理查询
     *
     * @param param
     * @return
     */
    @GetMapping("getAll")
    @ApiOperation(value = "订单管理查询")
    public Result<Page<Orders>> getAll(OrderGetAllParam param, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        Page page = cereShopOrderService.getAll(param, user);
        return new Result(page, CoReturnFormat.SUCCESS);
    }

    /**
     * 订单详情查询
     *
     * @param param
     * @return
     */
    @GetMapping("getById")
    @ApiOperation(value = "订单详情查询")
    public Result<OrderDetail> getById(OrderGetByIdParam param) throws CoBusinessException, Exception {
        OrderDetail detail = cereShopOrderService.getById(param);
        for (CartSku a : detail.getSkus()) {
            Integer state = cereShopProductService.getsheStateByid(a.getProductId());
            a.setShelveState(state);
            CereOrderProduct op = cereOrderAfterDAO.getByOrderIdSkuId(param.getOrderId(), a.getSkuId());
            a.setAfterState(op.getType());
        }
        return new Result<>(detail, CoReturnFormat.SUCCESS);
    }


    /**
     * 小程序立即支付
     *
     * @param param
     * @return
     */
    @PostMapping("gotoPay")
    @NoRepeatSubmit
    @ApiOperation(value = "小程序立即支付")
    @NoRepeatWebLog
    public Result<OrderPay> gotoPay(@RequestBody PayParam param, HttpServletRequest request) throws CoBusinessException, Exception {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        String ip = AppletPayUtil.getClientIp(request);
        OrderPay pay = cereShopOrderService.gotoPay(param, user, ip);
        return new Result(pay, CoReturnFormat.SUCCESS, user.getWechatName(), "小程序立即支付", GsonUtil.objectToGson(param));
    }


    /**
     * 填写退货物流单
     *
     * @param dilever
     * @return
     */
    @PostMapping("returnExpress")
    @NoRepeatSubmit
    @ApiOperation(value = "填写退货物流单")
    @NoRepeatWebLog
    public Result returnExpress(@RequestBody CereAfterDilever dilever, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        cereShopOrderService.returnExpress(dilever, user);
        return new Result(CoReturnFormat.SUCCESS, user.getWechatName(), "填写退货物流单", GsonUtil.objectToGson(dilever));
    }

    /**
     * 选择物流公司查询
     *
     * @return
     */
    @GetMapping("getExpressSelect")
    @ApiOperation(value = "选择物流公司查询")
    public Result<List<CerePlatformDict>> getExpressSelect() throws CoBusinessException {
        List<CerePlatformDict> list = cerePlatformDictService.getExpressSelect();
        return new Result(list, CoReturnFormat.SUCCESS);
    }

    /**
     * APP立即支付
     *
     * @param param
     * @return
     */
    @PostMapping("gotoAppPay")
    @NoRepeatSubmit
    @ApiOperation(value = "APP立即支付")
    @NoRepeatWebLog
    public Result<OrderPay> gotoAppPay(@RequestBody PayParam param, HttpServletRequest request) throws CoBusinessException, Exception {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        //获取客户端ip
        String ip = AppletPayUtil.getClientIp(request);
        OrderPay pay = cereShopOrderService.gotoAppPay(param, user, ip);
        return new Result(pay, CoReturnFormat.SUCCESS, user.getWechatName(), "APP立即支付", GsonUtil.objectToGson(param));
    }

    /**
     * H5立即支付
     *
     * @param param
     * @return
     */
    @PostMapping("gotoH5Pay")
    @NoRepeatSubmit
    @ApiOperation(value = "H5立即支付")
    @NoRepeatWebLog
    public Result<OrderPay> gotoH5Pay(@RequestBody PayParam param, HttpServletRequest request) throws CoBusinessException, Exception {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        String ip = AppletPayUtil.getClientIp(request);
        OrderPay pay = cereShopOrderService.gotoH5Pay(param, user, ip);
        return new Result(pay, CoReturnFormat.SUCCESS, user.getWechatName(), "H5立即支付", GsonUtil.objectToGson(param));
    }

    /**
     * 确认收货
     *
     * @param param
     * @return
     */
    @PostMapping("confirm")
    @NoRepeatSubmit
    @ApiOperation(value = "确认收货")
    @NoRepeatWebLog
    public Result confirm(@RequestBody OrderGetByIdParam param, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        cereShopOrderService.confirm(param, user);
        return new Result(CoReturnFormat.SUCCESS, user.getWechatName(), "确认收货", GsonUtil.objectToGson(param));
    }

    /**
     * 取消订单
     *
     * @param param
     * @return
     */
    @PostMapping("cancel")
    @NoRepeatSubmit
    @ApiOperation(value = "取消订单")
    @NoRepeatWebLog
    public Result cancel(@RequestBody OrderGetByIdParam param, HttpServletRequest request) throws CoBusinessException, Exception {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        cereShopOrderService.cancel(param, user);
        return new Result(CoReturnFormat.SUCCESS, user.getWechatName(), "取消订单", GsonUtil.objectToGson(param));
    }

    /**
     * 删除订单
     *
     * @param param
     * @return
     */
    @PostMapping("delete")
    @NoRepeatSubmit
    @ApiOperation(value = "删除订单")
    @NoRepeatWebLog
    public Result delete(@RequestBody OrderGetByIdParam param, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        cereShopOrderService.delete(param, user);
        return new Result(CoReturnFormat.SUCCESS, user.getWechatName(), "删除订单", GsonUtil.objectToGson(param));
    }

    /**
     * 添加评论
     *
     * @param param
     * @return
     */
    @PostMapping("addComment")
    @NoRepeatSubmit
    @ApiOperation(value = "添加评论")
    @NoRepeatWebLog
    public Result addComment(@RequestBody CommentSaveParam param, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        cereShopOrderService.addComment(param, user);
        return new Result(CoReturnFormat.SUCCESS, user.getWechatName(), "添加评论", GsonUtil.objectToGson(param));
    }

    /**
     * 追加评论
     *
     * @param param
     * @return
     */
    @PostMapping("addToComment")
    @NoRepeatSubmit
    @ApiOperation(value = "追加评论")
    @NoRepeatWebLog
    public Result addToComment(@RequestBody CommentSaveParam param, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        cereShopOrderService.addToComment(param, user);
        return new Result(CoReturnFormat.SUCCESS, user.getWechatName(), "追加评论", GsonUtil.objectToGson(param));
    }

    /**
     * 申请退款
     *
     * @param param
     * @return
     */
    @GetMapping("refund")
    @NoRepeatSubmit
    @ApiOperation(value = "申请退款")
    @NoRepeatWebLog
    public Result<List<CartSku>> refund(OrderGetByIdParam param, HttpServletRequest request) throws CoBusinessException {
        //获取当前登录账户
        CereBuyerUser user = (CereBuyerUser) request.getAttribute("user");
        List<CartSku> list = cereShopOrderService.refund(param, user);
        return new Result(list, CoReturnFormat.SUCCESS, user.getWechatName(), "申请退款", GsonUtil.objectToGson(param));
    }

    /**
     * 微信支付回调
     * todo:票务功能下单需要人工判断是否下架
     * 微信支付回调会多线程调用,所以使用synchronized锁
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @PostMapping("pay/rolBack")
    public synchronized void wxProPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("进入微信小程序支付回调");
        String xmlMsg = HttpKit.readData(request);
        log.info("微信小程序通知信息" + xmlMsg);
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlMsg);
        if (!EmptyUtils.isEmpty(resultMap)) {
            if (resultMap.get(StringEnum.WX_RETURN_CODE.getCode()).equals(StringEnum.WX_PAY_SUCCESS.getCode())) {
                String orderNo = resultMap.get("out_trade_no");
                log.info("回调out_trade_no=" + orderNo);
                log.info("微信小程序支付回调成功");
                //截取订单编号
                String[] split = orderNo.split("-");
                if (!EmptyUtils.isEmpty(split)) {
                    String orderFormId = split[0];
                    if (!EmptyUtils.isEmpty(orderFormId)) {
                        //使用redis缓存,判断订单是否是已经存储
                        List<String> range = redisTemplate.opsForList().range(StringEnum.PAY_SUCCESS_ORDERIDS.getCode(), 0, -1);
                        if (range == null || !range.contains(orderFormId)) {
                            try {
                                //存储进来的顶但订单
                                redisTemplate.opsForList().leftPush(StringEnum.PAY_SUCCESS_ORDERIDS.getCode(), orderFormId);
                                cereShopOrderService.handleWxLog(orderFormId, resultMap.get("transaction_id"), orderNo);
                            } catch (Exception e) {
                                e.printStackTrace();
                                //如果出现问题,则删除没有存入的订单id,保证存入数据库后才会redis存储
                                redisTemplate.opsForList().remove(StringEnum.PAY_SUCCESS_ORDERIDS.getCode(), 0, orderFormId);
                            }
                        }
                    }
                }
            }
        } else {
            log.info("map为null");
        }
        String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        response.getWriter().write(result);
    }

    /**
     * 微信退款回调
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @PostMapping("refund/rolBack")
    public synchronized void wxRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("进入微信小程序退款回调");
        String xmlMsg = HttpKit.readData(request);
        log.info("微信小程序通知信息" + xmlMsg);
        Map<String, String> resultMap = PaymentKit.xmlToMap(xmlMsg);
        if (!EmptyUtils.isEmpty(resultMap)) {
            if (resultMap.get(StringEnum.WX_RETURN_CODE.getCode()).equals(StringEnum.WX_PAY_SUCCESS.getCode())) {
                //获取微信返回数据进行解密
                String req_info = resultMap.get("req_info");
                String str = EmptyUtils.decryption(req_info, key);
                Map<String, String> map = PaymentKit.xmlToMap(str);
                String orderNo = map.get("out_trade_no");
                log.info("回调out_trade_no=" + orderNo);
                log.info("微信小程序退款回调成功");
                //截取订单编号
                String[] split = orderNo.split("-");
                if (!EmptyUtils.isEmpty(split)) {
                    String orderFormId = split[0];
                    if (!EmptyUtils.isEmpty(orderFormId)) {
                        cereShopOrderService.handleRefundWxLog(orderFormId, map.get("transaction_id"), orderNo);
                    }
                }
            }
        } else {
            log.info("map为null");
        }
        String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        response.getWriter().write(result);
    }

    /**
     * 物流信息查询
     *
     * @param param
     * @return
     */
    @GetMapping("getDilevery")
    @ApiOperation(value = "物流信息查询")
    public Result<List<Dilevery>> getDilevery(DileveryParam param) throws CoBusinessException, Exception {
        List<Dilevery> dileveries = cereShopOrderService.getDilevery(param);
        return new Result(dileveries, CoReturnFormat.SUCCESS);
    }

    /**
     * 支付业务处理接口
     *
     * @param param
     * @return
     */
    @PostMapping("pay")
    @ApiOperation(value = "支付业务处理接口")
    public Result pay(@RequestBody PayParam param) throws CoBusinessException, Exception {
        cereShopOrderService.pay(param);
        return new Result(CoReturnFormat.SUCCESS);
    }


}
